home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 416_01 / spiro / spiro2.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-15  |  9.9 KB  |  520 lines

  1. // Spirograph simulator for 640x480 VGA mono
  2. // Borland C++ source
  3. // Need to add in the EGAVGA BGI driver to your graphics.lib
  4. // using bin2obj and then tlib
  5. //
  6. /******************************************************
  7. Nigel Salt
  8. 25 Lower Station Rd
  9. Crayford
  10. Kent
  11. DA1 3PY
  12. UK
  13.  
  14. Phone +44 322 553260
  15.  
  16. Email nao@cix.complink.co.uk
  17. ******************************************************/
  18.  
  19.  
  20. #include <graphics.h>
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <conio.h>
  24. #include <math.h>
  25. #include <ctype.h>
  26. #include <dos.h>
  27.  
  28. void initsin(void);
  29. void initparm(void);
  30. int  getint3xy(int x, int y, char far *prompt);
  31. int  getchxy(int x, int y, char far *prompt);
  32. void spiro(void);
  33. void setdrawport(void);
  34. void setstatport(void);
  35. void printstatus(void);
  36. void getpx(void);
  37. void getpy(void);
  38. void getpxr1(void);
  39. void getpyr1(void);
  40. void getpinorout(void);
  41. void getpr2(void);
  42. void getpr3(void);
  43. void getpinc(void);
  44. int  getparm(void);
  45. void highopt(int opt);
  46. void unhighopt(int opt);
  47. void writeopt(int opt);
  48. int  xgetch(void);
  49.  
  50. #define PI  (3.141592654)
  51. #define IN  (-1)
  52. #define OUT (1)
  53. #define UNITSINCIRC (4000)
  54. #define GO 1
  55. #define STOP 0
  56. #define RIGHTKEY 256*77
  57. #define LEFTKEY  256*75
  58. #define SHIFTAB  256*15
  59. #define ESC      27
  60. #define SINMULT  (0x100000L)
  61. #define MODMULT  (0x100000L)
  62. long sintab[UNITSINCIRC+1];
  63. int x=320,
  64.     y=235,
  65.     xr1=100,
  66.     yr1=100,
  67.     r2=35,
  68.     r3=35,
  69.     inc=10,
  70.     flag=IN;
  71. char inorout;
  72. double modulus;
  73.  
  74.  
  75. int main(void)
  76. {
  77.    /* request auto detection */
  78.    int gdriver = DETECT, gmode, errorcode;
  79.    int parmret;
  80.  
  81.    /* register a driver that was added into graphics.lib */
  82.    /* For information on adding the driver, see the
  83.    /* BGIOBJ section of UTIL.DOC */
  84.    errorcode = registerbgidriver(EGAVGA_driver);
  85.  
  86.    /* report any registration errors */
  87.    if (errorcode < 0)
  88.    {
  89.       printf("Graphics error: %s\n", grapherrormsg(errorcode));
  90.       printf("Press any key to halt:");
  91.       getch();
  92.       exit(1); /* terminate with an error code */
  93.    }
  94.    initsin();
  95.  
  96.    /* initialize graphics and local variables */
  97.    initgraph(&gdriver, &gmode, "");
  98.  
  99.    /* read result of initialization */
  100.    errorcode = graphresult();
  101.    if (errorcode != grOk)  /* an error occurred */
  102.    {
  103.       printf("Graphics error: %s\n", grapherrormsg(errorcode));
  104.       printf("Press any key to halt:");
  105.       getch();
  106.       exit(1); /* terminate with an error code */
  107.    }
  108.  
  109.    /* draw a line */
  110.    line(0, 470, getmaxx(), 470);
  111.    /* initparm();
  112.       spiro();
  113.    */
  114.    printstatus();
  115.    parmret=getparm();
  116.    while (parmret!=STOP)
  117.      {
  118.      spiro();
  119.      printstatus();
  120.      parmret=getparm();
  121.      };
  122.    /* clean up */
  123.    closegraph();
  124.    return 0;
  125. }
  126.  
  127. void initsin(void)
  128. {
  129.   int i;
  130.   int dotcount=100;
  131.   double inc=2*PI/UNITSINCIRC;
  132.   double ang=0;
  133.   printf("Initialising SIN table");
  134.   for (i=0;i<UNITSINCIRC;i++)
  135.     {
  136.     sintab[i]=sin(ang)*SINMULT;
  137.     ang+=inc;
  138.     dotcount--;
  139.     if (dotcount<0)
  140.       {
  141.       dotcount=100;
  142.       printf(".");
  143.       };
  144.     };
  145. };
  146.  
  147. void initparm(void)
  148. {
  149.   getpx();
  150.   getpy();
  151.   getpxr1();
  152.   getpyr1();
  153.   getpinorout();
  154.   getpr2();
  155.   getpr3();
  156.   getpinc();
  157. };
  158.  
  159. void highopt(int opt)
  160. {
  161.   setcolor(LIGHTRED);
  162.   writeopt(opt);
  163. };
  164.  
  165. void unhighopt(int opt)
  166. {
  167.   setcolor(WHITE);
  168.   writeopt(opt);
  169. };
  170.  
  171. void writeopt(int opt)
  172. {
  173.   switch (opt)
  174.     {
  175.     case 0:
  176.       moveto(0,0);
  177.       outtext("GO");
  178.       break;
  179.     case 1:
  180.       moveto(24,0);
  181.       outtext("EXIT");
  182.       break;
  183.     case 2:
  184.       moveto(64,0);
  185.       outtext("CLS");
  186.       break;
  187.     case 3:
  188.       moveto(96,0);
  189.       outtext("XC:");
  190.       break;
  191.     case 4:
  192.       moveto(152,0);
  193.       outtext("YC:");
  194.       break;
  195.     case 5:
  196.       moveto(208,0);
  197.       outtext("XRS:");
  198.       break;
  199.     case 6:
  200.       moveto(272,0);
  201.       outtext("YRS:");
  202.       break;
  203.     case 7:
  204.       moveto(336,0);
  205.       if (flag==IN)
  206.         outtext("IN ");
  207.       else
  208.         outtext("OUT");
  209.       break;
  210.     case 8:
  211.       moveto(368,0);
  212.       outtext("RAD:");
  213.       break;
  214.     case 9:
  215.       moveto(432,0);
  216.       outtext("PEN:");
  217.       break;
  218.     case 10:
  219.       moveto(496,0);
  220.       outtext("INC");
  221.       break;
  222.     default:
  223.       break;
  224.     };
  225. };
  226.  
  227. int getparm(void)
  228. {
  229.   int inch,go,stop;
  230.   int curopt;
  231.   setstatport();
  232.   highopt(0);
  233.   curopt=0;
  234.   go=0;
  235.   stop=0;
  236.   while (!go&&!stop)
  237.     {
  238.     while (!kbhit())
  239.       {
  240.       highopt(curopt);
  241.       delay(100);
  242.       unhighopt(curopt);
  243.       delay(100);
  244.       };
  245.     inch=xgetch();
  246.     switch (inch)
  247.       {
  248.       case ESC:
  249.         return STOP;
  250.       case SHIFTAB:
  251.       case LEFTKEY:
  252.         printstatus();
  253.         curopt--;
  254.         if (curopt<0) curopt=10;
  255.         highopt(curopt);
  256.         break;
  257.       case '\t':
  258.       case ' ':
  259.       case RIGHTKEY:
  260.         printstatus();
  261.         curopt++;
  262.         if (curopt>10) curopt=0;
  263.         highopt(curopt);
  264.         break;
  265.       case '\r':
  266.         setstatport();
  267.         clearviewport();
  268.         switch (curopt)
  269.           {
  270.           case 0:
  271.             return GO;
  272.           case 1:
  273.             return STOP;
  274.           case 2:
  275.             setdrawport();
  276.             clearviewport();
  277.             setstatport();
  278.             break;
  279.           case 3:
  280.             getpx();
  281.             break;
  282.           case 4:
  283.             getpy();
  284.             break;
  285.           case 5:
  286.             getpxr1();
  287.             break;
  288.           case 6:
  289.             getpyr1();
  290.             break;
  291.           case 7:
  292.             getpinorout();
  293.             break;
  294.           case 8:
  295.             getpr2();
  296.             break;
  297.           case 9:
  298.             getpr3();
  299.             break;
  300.           case 10:
  301.             getpinc();
  302.             break;
  303.           default:
  304.             break;
  305.           };
  306.         printstatus();
  307.         highopt(curopt);
  308.         break;
  309.       default:
  310.         break;
  311.  
  312.       };
  313.     };
  314.  
  315.   moveto(0,0);
  316.   setcolor(WHITE);
  317.   outtext("GO");
  318.   return GO;
  319. };
  320.  
  321. void getpx(void)
  322. {
  323.   x=-1;
  324.   while (x<1||x>getmaxx())
  325.     x=getint3xy(0,472,"XCOORD OF CENTRE (0-639): ");
  326. };
  327.  
  328. void getpy(void)
  329. {
  330.   y=-1;
  331.   while (y<1||y>469)
  332.     y=getint3xy(0,472,"YCCORD OF CENTRE (0-469): ");
  333. };
  334.  
  335. void getpxr1(void)
  336. {
  337.   xr1=-1;
  338.   while (xr1<1||xr1>getmaxx())
  339.     xr1=getint3xy(0,472,"X RADIUS OF STILL OVAL: ");
  340. };
  341.  
  342. void getpyr1(void)
  343. {
  344.   yr1=-1;
  345.   while (yr1<1||yr1>469)
  346.     yr1=getint3xy(0,472,"Y RADIUS OF STILL OVAL: ");
  347. };
  348.  
  349. void getpinorout(void)
  350. {
  351.   inorout='x';
  352.   flag=IN;
  353.   while (inorout!='I'&&inorout!='O')
  354.     inorout=toupper(getchxy(0,472,"MOVE INSIDE OR OUT (I/O): "));
  355.   if (inorout=='O') flag=OUT;
  356. };
  357.  
  358. void getpr2(void)
  359. {
  360.   r2=-1;
  361.   while (r2<1||r2>getmaxx())
  362.     r2=getint3xy(0,472,"RADIUS OF MOVING CIRCLE: ");
  363. };
  364.  
  365. void getpr3(void)
  366. {
  367.   r3=-1;
  368.   while (r3<1||r3>getmaxx())
  369.     r3=getint3xy(0,472,"PEN POSITION: ");
  370. };
  371.  
  372. void getpinc(void)
  373. {
  374.   inc=-1;
  375.   while (inc<1||inc>999)
  376.     inc=getint3xy(0,472,"INCREMENT: ");
  377.  
  378. };
  379.  
  380. int getint3xy(int x, int y, char far *prompt)
  381. {
  382.   int inch,retval,numlen;
  383.   char buff[5];
  384.   struct viewporttype oldvp;
  385.   getviewsettings(&oldvp);
  386.   setviewport(x,y,getmaxx()-1,y+7,1);
  387.   numlen=0;
  388.   retval=0;
  389.   inch='\0';
  390.   buff[1]='\0';
  391.   outtext(prompt);
  392.   while (inch!='\r'&&numlen<4)
  393.     {
  394.     inch=getch();
  395.     if (inch<'0'||inch>'9') continue;
  396.     retval*=10;
  397.     retval+=inch-'0';
  398.     numlen++;
  399.     buff[0]=inch;
  400.     outtext(buff);
  401.     };
  402.   clearviewport();
  403.   setviewport(oldvp.left,oldvp.top,oldvp.right,oldvp.bottom,oldvp.clip);
  404.  
  405.   return retval;
  406. };
  407.  
  408. int getchxy(int x, int y, char far *prompt)
  409. {
  410.   int inch,retval;
  411.   struct viewporttype oldvp;
  412.   getviewsettings(&oldvp);
  413.   setviewport(x,y,getmaxx()-1,y+7,1);
  414.   outtext(prompt);
  415.   retval=getch();
  416.   clearviewport();
  417.   setviewport(oldvp.left,oldvp.top,oldvp.right,oldvp.bottom,oldvp.clip);
  418.   return retval;
  419. };
  420.  
  421. void spiro(void)
  422. {
  423.   long rots;
  424.   double modulus;
  425.   long x1mult, x2mult, y1mult, y2mult;
  426.   long avr1,ang1;
  427.   unsigned long total, uli, progmax, progcur, proglin;
  428.   int ang;
  429.   int posx, posy;
  430.   progcur=0;
  431.   proglin=0;
  432.   avr1=(xr1+yr1+.5)/2;
  433.   modulus=-(xr1+yr1)/2;
  434.   modulus/=r2;
  435.   rots=1;
  436.   /* Find smallest number of rotations that is more or less exactly
  437.      divisible by the radius of the moving circle */
  438.   while ((rots*avr1)%r2>0)
  439.     rots++;
  440.   total=UNITSINCIRC*rots;
  441.   progmax=total/20;
  442.   setdrawport();
  443.   x1mult=xr1+(flag*r2);
  444.   x2mult=flag*r3;
  445.   y1mult=yr1+(flag*r2);
  446.   y2mult=flag*r3;
  447.   for (uli=0;uli<total;uli+=inc, progcur+=inc)
  448.     {
  449.     if (kbhit()) break;
  450.     if (progcur>progmax)
  451.       {
  452.       setstatport();
  453.       setfillstyle(SOLID_FILL,EGA_LIGHTRED);
  454.       bar(proglin*32,1,(proglin+1)*32,8);
  455.       proglin++;
  456.       progcur=0;
  457.       setdrawport();
  458.       };
  459.     ang1=uli*modulus;
  460.     ang1%=UNITSINCIRC;
  461.     if (ang1<0) ang1+=UNITSINCIRC;
  462.     ang=(int)(uli%UNITSINCIRC);
  463.  
  464.     /* Calculate xpos */
  465.     posx=x;
  466.     posx+=(int)((sintab[ang]*x1mult)/SINMULT);
  467.     posx-=(int)((x2mult*sintab[ang1])/SINMULT);
  468.  
  469.     /* Add one quarter rotation for cosine */
  470.     ang=(ang+UNITSINCIRC/4)%UNITSINCIRC;
  471.     ang1=(ang1+UNITSINCIRC/4)%UNITSINCIRC;
  472.  
  473.     /* Calculate ypos */
  474.     posy=y;
  475.     posy+=(int)((sintab[ang]*y1mult)/SINMULT);
  476.     posy-=(int)((y2mult*sintab[ang1])/SINMULT);
  477.  
  478.     putpixel(posx,posy,15);
  479.     };
  480.  
  481.  
  482. };
  483.  
  484. void setdrawport(void)
  485. {
  486.   setviewport(0,0,639,469,1);
  487. };
  488.  
  489. void setstatport(void)
  490. {
  491.   setviewport(0,472,639,479,1);
  492. };
  493.  
  494.  
  495. void printstatus(void)
  496. {
  497.   char buffer[81];
  498.   char inoutbuf[10];
  499.   setcolor(WHITE);
  500.   if (flag==IN)
  501.    sprintf(inoutbuf,"IN ");
  502.   else
  503.    sprintf(inoutbuf,"OUT");
  504.   setstatport();
  505.   clearviewport();
  506.   sprintf(buffer,
  507.    "GO EXIT CLS XC:%3d YC:%3d XRS:%3d YRS:%3d %s RAD:%3d PEN:%3d INC:%3d",
  508.    x,y,xr1,yr1,inoutbuf,r2,r3,inc);
  509.   outtext(buffer);
  510. };
  511.  
  512. int xgetch(void)
  513. {
  514.   int retkey;
  515.   retkey=getch();
  516.   if (retkey>0) return retkey;
  517.   retkey=256*getch();
  518.   return retkey;
  519. }
  520.